use super::*;

#[derive(Debug, Clone)]
pub struct Table<'a> {
	// Fixed	version	Version number of the justification table (0x00010000 for the current version).
	pub version: i32,
	// UInt16	format	Format of the justification table (set to 0).
	pub format: u16,
	// UInt16	horizOffset	Byte offset from the start of the justification table to the header for tables that contain justification information for horizontal text. If you are not including this information, store 0.
	pub horiz: Option<Justification<'a>>,
	// UInt16	vertOffset	Byte offset from the start of the justification table to the header for tables that contain justification information for vertical text. If you are not including this information, store 0.
	pub vert: Option<Justification<'a>>,
}
impl<'a> Table<'a> {
	pub fn parse(num_glyphs: u16, data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			version: s.read()?,
			format: s.read()?,
			horiz: s.read_at_offset16(data).and_then(|data| Justification::parse(num_glyphs, data)),
			vert: s.read_at_offset16(data).and_then(|data| Justification::parse(num_glyphs, data)),
		})
	}
}

#[derive(Debug, Clone)]
pub struct Justification<'a> {
	// UInt16	justClassTableOffset	Offset to the justification category state table.
	pub just_class: Option<aat::State<'a>>,
	// UInt16	wdcTableOffset	Offset from start of justification table to start of the subtable containing the width delta factors for the glyphs in your font.
	pub wdc: Option<Offset16>,
	// UInt16	pcTableOffset	Offset from start of justification table to start of postcompensation subtable (set to zero if none).
	pub pc: Option<Offset16>,
	// variable	lookupTable	Lookup table associating glyphs with width delta clusters. See the description of Width Delta Clusters table for details on how to interpret the lookup values.
	pub lookup: aat::Lookup<'a>,
	// variable	widthDeltaClusters	The width delta clusters table.
	// variable	postcompTable	The postcompensation subtable, if present in the font.
}
impl<'a> Justification<'a> {
	fn parse(num_glyphs: u16, data: &'a [u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			just_class: s.parse_at_offset16(data),
			wdc: s.read()?,
			pc: s.read()?,
			lookup: aat::Lookup::parse(num_glyphs, s.tail()?)?,
		})
	}
}

// UInt32	count	Number of width delta pair records that follow.
// WidthDeltaPair	wdPairs	The width delta pairs records
pub type WidthDeltaCluster<'a> = LazyArray32<'a, WidthDeltaPair>;

#[derive(Debug, Clone, Copy)]
pub struct WidthDeltaPair {
	// UInt32	justClass	The justification category associated with the wdRecord field. Only 7 bits of this field are used. (The other bits are used as padding to guarantee longword alignment of the following record).
	pub just_class: u32,
	// JustWidthDeltaEntry	wdRecord	The actual width delta record.
	pub wd_record: JustWidthDeltaEntry,
}
impl FromData for WidthDeltaPair {
	const SIZE: usize = 24;
	fn parse(data: &[u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			just_class: s.read()?,
			wd_record: s.read()?,
		})
	}
}

#[derive(Debug, Clone, Copy)]
pub struct JustWidthDeltaEntry {
	// Fixed	beforeGrowLimit	The ratio by which the advance width of the glyph is permitted to grow on the left or top side.
	pub before_grow_limit: Fixed,
	// Fixed	beforeShrinkLimit	The ratio by which the advance width of the glyph is permitted to shrink on the left or top side.
	pub before_shrink_limit: Fixed,
	// Fixed	afterGrowLimit	The ratio by which the advance width of the glyph is permitted to grow on the right or bottom side.
	pub after_grow_limit: Fixed,
	// Fixed	afterShrinkLimit	The ratio by which the advance width of the glyph is at most permitted to shrink on the right or bottom side.
	pub after_shrink_limit: Fixed,
	// UInt16	growFlags	Flags controlling the grow case.
	pub grow_flags: u16,
	// UInt16	shrinkFlags	Flags controlling the shrink case.
	pub shrink_flags: u16,
}
impl FromData for JustWidthDeltaEntry {
	const SIZE: usize = 20;
	fn parse(data: &[u8]) -> Option<Self> {
		let mut s = Stream::new(data);
		Some(Self {
			before_grow_limit: s.read()?,
			before_shrink_limit: s.read()?,
			after_grow_limit: s.read()?,
			after_shrink_limit: s.read()?,
			grow_flags: s.read()?,
			shrink_flags: s.read()?,
		})
	}
}

#[derive(Debug, Clone)]
pub struct PostCompensations<'a> {
	// variable	pcLookupTable	Lookup table associating glyphs with postcompensation action records. See below for details on how to interpret the lookup values.
	pub lookup: aat::Lookup<'a>,
	// variable	pcActionRecords	Actions records whose offsets are contained in the previous lookup table.
	pub data: &'a [u8],
}
impl<'a> PostCompensations<'a> {
	pub fn parse(num_glyphs: u16, data: &'a [u8]) -> Option<Self> {
		Some(Self {
			lookup: aat::Lookup::parse(num_glyphs, data)?,
			data,
		})
	}
}

// UInt32	actionCount	Number of ActionSubrecord records in the following array.
// ActionSubrecord	actSubrecord[]	Array of ActionSubrecord records.
pub type PostcompensationAction<'a> = LazyArray32<'a, ActionSubrecord<'a>>;

#[derive(Debug, Clone, Copy)]
pub struct ActionSubrecord<'a> {
	// UInt16	actionClass	The JustClass value associated with this ActionSubrecord.
	pub action_class: u16,
	// UInt16	actionType	The type of postcompensation action.
	pub action_type: u16,
	// UInt32	actionLength	Length of this ActionSubrecord record, which must be a multiple of 4.
	pub action_length: u32,
	pub data: &'a [u8],
	// variable	actionData	Data. The format of this data depends on the value of the actionType field.
	// variable	padding	Extra bytes, if needed, to guarantee that the length of this ActionSubrecord is a multiple of 4.
}
